Upgrade from XDK3.x to XDK4.0
Core Packages
Following packages served as the core.
npm i \
  @accedo/xdk-base-modules \
  @accedo/xdk-config \
  @accedo/xdk-core \
  @accedo/xdk-log \
  @accedo/xdk-virtual-key
Device Packages
Install the device package(s) that are required for your app.
npm i @accedo/xdk-device-workstation {add more if needed.}
Polyfill
Similar to React 16, XDK4 is depended on lots of ESNext features, including Map collection, Optional Chaining and Async/Await, to name but a few.
We would recommend using core-js to provide the polyfill.
Replace XDK3 Imports with XDK4's
TVKeys
TVKeys are now exported from @accedo/xdk-virtual-key
- import { CONSTANT } from 'xdk3';
+ import { vKey } from '@accedo/xdk-virtual-key';
- const { UP, DOWN, LEFT, RIGHT } from CONSTANT;
+ const { UP, DOWN, LEFT, RIGHT } from vKey;
If you are going to use the a constant subset of TVKey across multiple components, you can do the following.
- import { CONSTANT } from 'xdk3';
+ import { UP, DOWN, LEFT, RIGHT, SO_ON_AND_SO_FORTH } from './xdkKeys';
+ // xdkKeys.js
+ import { vKey } from '@accedo/xdk-virtual-key';
+ const { UP, DOWN, LEFT, RIGHT, SO_ON_AND_SO_FORTH } = vKey;
+ export { UP, DOWN, LEFT, RIGHT, SO_ON_AND_SO_FORTH };
Environment object
The environment object, where the app add all the event listeners to observe
System's and Player's status changes is exported by @accedo/xdk-core module.
All previously available events are still available in XDK4.
- import { environment } from 'xdk3';
+ import { environment } from '@accedo/xdk-core';
+ // No need to change
environment.addEventListener(environment.SYSTEM.KEYDOWN, this.doKeyAction);
+ // No need to change as well.
environment.removeEventListener(environment.SYSTEM.KEYDOWN, this.doKeyAction);
Device related properties are moved to device object
platform, system, storageManager are guaranteed to be available when the
device is loaded. We would recommend using the following way to access them,
instead of importing them directly as named import.
- import { environment, platform } from 'xdk3';
+ import { environment, device } from '@accedo/xdk-core';
environment.addEventListener(environment.DEVICE.ONLOAD, () => {
+  const { platform, system, storageManager } = device;
  console.log(platform);
});
xdk.config.js
The structure of xdk.config.js is changed substantially. Below is a sample config.
import tizenDetection from '@accedo/xdk-device-samsung-tizen/esm/detection.js';
import workstationDetection from '@accedo/xdk-device-workstation/esm/detection.js';
const COOKIE_ONLY = {
  cookieName: 'xdk4-dva'
};
// The file is written in ES6 and is expected to be transpiled and imported
// into the app code later.
const COOKIE_AND_POLLER = {
  ...COOKIE_ONLY,
  network: {
    polling: {
      interval: 30
    }
  }
};
const CONFIG = {
  devices: {
    // `packages` only concern about configuration of device package loading.
    packages: [
      {
        // Each package object contains 4 entries.
        // `id` determine the device package ID returned by devicePackage.getId().
        id: 'samsung-tizen',
        // `detection` returns a function that returns the dynamic import Promise
        // of a package's detection module.
        detection: () => async () => ({ default: workstationDetection }),
        // `defaultConfig` returns a function that returns the dynamic import Promise
        // of a package's default config.
        defaultConfig: () =>
          import('@accedo/xdk-device-samsung-tizen/dist/defaultConfig.js'),
        // `DevicePackage` returns a function that returns the dynamic import Promise
        // of a package's Device Package constructor.
        DevicePackage: () =>
          import('@accedo/xdk-device-samsung-tizen/dist/DevicePackage.js')
      },
      {
        id: 'workstation',
        detection: () => async () => ({ default: workstationDetection }),
        defaultConfig: () =>
          import('@accedo/xdk-device-workstation/dist/defaultConfig.js'),
        DevicePackage: () =>
          import('@accedo/xdk-device-workstation/dist/DevicePackage.js')
      }
    ],
    // `details` concern about other configuration, for example. Name of the cookie
    // or whether using network polling or not.
    details: {
      workstation: COOKIE_AND_POLLER,
      'samsung-tizen': COOKIE_ONLY
    }
  },
  // logging configuration goes here. It will be read by the
  // `@accedo/xdk-log` module.
  logging: {
    level: -1
  }
};
export default CONFIG;
Loading the config and XDK
First, XDK config needs to be imported and loaded. Below demonstrate a way to do it in a discreet manner.
// index.js
import React from 'react';
import { render } from 'react-dom';
// Import preflight code before any app logic.
import './preflight';
import App from './App';
render(<App>{'Hello XDK4'}</App>, document.getElementById('root'));
// preflight.js
// XDK/React polyfill
import 'core-js';
import xdkConfigStore from '@accedo/xdk-config';
import config from './xdk.config';
xdkConfigStore.load(config);
// XDK Config is now loaded.
// App.js
import React from 'react';
import xdk from '@accedo/xdk-core';
class App extends React.Component {
  async componentDidMount() {
    // This will trigger the loading of XDK. The loading function
    // will return a Promise, which will be resolved when,
    //
    // - Current device is identified, and
    // - Device Package for the current device is loaded, and
    // - Media Manager created a default Media instance for the app, and
    // - Storage Manager created the default Storage instance for the app.
    //
    // If one of the above condition failed, the returning Promise will
    // be rejected.
    await xdk.load();
  }
}
Building Toolchain
(Viki) Babel and corejs3
The whole XDK4 use a runtime library @babel/runtime-corejs3, to avoid
duplication of helper function injected by Babel. The library, however, export
function in ES6 syntax and tranpsilation is needed.
webpack/dev/dev-config.js
{
  test: /\.js$/,
  exclude: jsExcludePath,
-  include: srcPath,
+  include: [/runtime-corejs3/, srcPath],
  use: jsLoaders
},
webpack/prod/prod-common-config.js
const jsIncludePath = transpileNodeModules
  ? [
      /@accedo/,
+      /runtime-corejs3/,
      /vdkweb/,
      // Include modules here to transplie with
      staticRootPath
helpers/registerBabel.js
// Parse it to JSON.
const config = JSON.parse(babelrc);
+ config.only = [/src/, /corejs3/];
+
// This hooks into node's 'require' and automatically compiles files on the fly.
// All subsequent files required by node with the extensions .es6, .es, .jsx and .js will be transformed by Babel.
// WARNING: This should not be used in production.
(Viki) Piping package
If you are using Viki helpers/startDevServer.js, you may want to consider
removing the piping clause.
- // If in dev mode we'll restart the server when detecting file changes
- if (__DEVELOPMENT__) {
-   require('piping')({
-     hook: true,
-     ignore: /(\/\.|~$|\.json|\.scss$)/i
-   });
-   require('localstorage-polyfill');
- }
+ require('localstorage-polyfill');
(Viki) Dev Server Mock
Development server doesn't seems to know the MediaError exposed by a browser.
A quick patch would be
// ./mocks.js
global.MediaError = class MediaError {
  static MEDIA_ERR_ABORTED = 1;
  static MEDIA_ERR_NETWORK = 2;
  static MEDIA_ERR_DECODE = 3;
  static MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
};
// ./server.js
import './mocks';